package net.whzjkj.gateway.tcpserver.handler;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;
import net.whzjkj.gateway.core.codce.JT808MessageDecoder;
import net.whzjkj.gateway.core.handler.AbstractServerHandler;
import net.whzjkj.gateway.core.session.Session;
import net.whzjkj.gateway.core.session.TCPSessionManager;
import net.whzjkj.gateway.core.util.HexUtils;
import net.whzjkj.gateway.core.util.JT808ProtocolUtils;
import net.whzjkj.gateway.model.vo.PackageData;
import net.whzjkj.gateway.tcpserver.adapter.TerminalMessageProcessorAdapter;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @description:
 * @author: Mr.Hu
 * @create: 2018-11-05 20:37
 **/
@Slf4j
@Component
@ChannelHandler.Sharable
public class TcpServerHandler extends AbstractServerHandler {
    @Resource
    private TerminalMessageProcessorAdapter terminalMessageProcessor;
    @Resource
    private JT808MessageDecoder messageDecoder;
    @Resource
    private TCPSessionManager sessionManager;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        try {
            if (msg instanceof ByteBuf){
                ByteBuf buf = (ByteBuf) msg;
                if (buf.readableBytes() <= 0) {
                    return;
                }
                byte[] tmp = new byte[buf.readableBytes()];
                buf.readBytes(tmp);
                //转译接收的消息
                byte[] bs = JT808ProtocolUtils.translationReceive(tmp);
                PackageData packageData = messageDecoder.byte2PackageData(bs);
                packageData.setChannel(ctx.channel());
                terminalMessageProcessor.processTerminalMessage(packageData);
                log.info(HexUtils.toHexString(bs));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            release(msg);
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {

    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)
        log.error("发生异常:{}", cause.getMessage());
        cause.printStackTrace();
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        ctx.fireChannelRegistered();
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {

    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Session session = Session.buildSession(ctx.channel());
        sessionManager.put(session.getId(), session);
        log.info("终端连接:{}", session);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        final String sessionId = ctx.channel().id().asLongText();
        Session session = sessionManager.findBySessionId(sessionId);
        this.sessionManager.removeBySessionId(sessionId);
        log.info("终端断开连接:{}", session);
        ctx.channel().close();
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (IdleStateEvent.class.isAssignableFrom(evt.getClass())) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                Session session = this.sessionManager.removeBySessionId(Session.buildId(ctx.channel()));
                log.error("服务器主动断开连接:{}", session);
                ctx.close();
            }
        }
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {

    }

    private void release(Object msg) {
        try {
            ReferenceCountUtil.release(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
